package org.gc.amino.ia.scalar;

import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Float;
import java.util.List;

import org.gc.amino.engine.mote.Mote;
import org.gc.amino.engine.terrainmap.PointD;
import org.gc.amino.ia.MoteSimulator;
import org.gc.amino.universe.Universe;

public class ScalarField {
	List<? extends ScalarFieldSourcePotential> sources;
	float ref_radius;

	public ScalarField(List<MoteSimulator> mote_list) {
		this.sources = mote_list;
		this.ref_radius = 1.0f;
	}

	void setRefRadius(float radius) {
		this.ref_radius = radius;
	}

	public float computeFieldPotentialFromMote2(MoteSimulator mote,
			Point2D.Float point, int courage) {
		float field_value = 0;
		float radius = mote.getRadius();

		// if(point.distance(this.position)< 5* this.radius){
		if (ref_radius < radius)
			field_value = -courage * radius; // repulsive potential
		else
			field_value = radius; // attractive potential
		// }
		// float distance_squared = (float) (point.distanceSq(this.position) -
		// Util.sqr(ref_radius + this.radius));
		float distance_squared = (float) (point.distance(mote.getPosition())
				- ref_radius - radius * 0.5f);
		distance_squared = distance_squared * distance_squared;
		return field_value / distance_squared;
	}

	/*
	 * Calculates the field potential in a point in space by summing the
	 * contributions of all sources excluding one.
	 */
	public float computeFieldPotential(float ref_radius, Point2D.Float point,
			ScalarFieldSourcePotential excluded, int courage) {
		float potential = 0.f;

		for (ScalarFieldSourcePotential source : this.sources) {
			if (source != excluded) {
				potential += source.visit(this, point, courage);
			}
		}

		return potential;
	}

	public static int findBestDirection(Universe universe, int courage, MoteSimulator you) {
		final int NumberOfDirections = 7;
		PointD[] cardinal_directions;
	    cardinal_directions = new PointD[NumberOfDirections + 1];
		cardinal_directions[0] = new PointD(0, 0);
		for(int i = 1; i < NumberOfDirections + 1; ++i) {
    		double angle = 2 * Math.PI / i;
    		cardinal_directions[i] = new PointD(Math.cos(angle), Math.sin(angle));
    	}
				
		int best = 0;
    	//MoteSimulator you = new MoteSimulator(m);
    	
    	float probing_dist = you.getRadius();
    	
    	float min_potential = universe.computeFieldPotential(
				you.getRadius(), 
				new Point2D.Float(
					you.getPosition().x + probing_dist * (float)cardinal_directions[0].x, 
					you.getPosition().y + probing_dist * (float)cardinal_directions[0].y), 
				you,
				courage);
    	
    	for(int direction = 1; direction < NumberOfDirections + 1; ++direction) {
    		float potential = universe.computeFieldPotential(
    				you.getRadius(), 
    				new Point2D.Float(
						you.getPosition().x + (float)cardinal_directions[direction].x, 
						you.getPosition().y + (float)cardinal_directions[direction].y), 
    				you,
    				courage);
    		if(potential < min_potential) {
    			min_potential = potential;
    			best = direction;
    		}
    	}
    	
    	System.out.println("best dir: " + best + " potential: " + min_potential);
    	
		return best;
    }

}
